package com.mdjukebox.model.jukeboxfacade.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.mdjukebox.model.jukeboxfacade.vo.CancionCVO;
import com.mdjukebox.model.vo.PeticionVO;
import com.mdjukebox.util.GlobalNames;
import com.util.configuration.ConfigurationParametersManager;
import com.util.configuration.MissingConfigurationParameterException;
import com.util.exceptions.InstanceNotFoundException;
import com.util.exceptions.InternalErrorException;
import com.util.sql.GeneralOperations;

public class DJDAO {
	
	private static Log log = LogFactory.getLog(DJDAO.class);
	
	
	/**
	 * cuantas canciones se pidieron antes que la primera vez que se pidio la mia
	 * = canciones que se han pedido antes
	 *   y que se puedan reproducir
	 * = canciones que se han pedido ante
	 *   no se han reproducido todavia
	 *   o hace mas de una hora que se han reproducido
	 */
	public int getNumAnteriores(Connection connection, int idCancion)
		throws InstanceNotFoundException, InternalErrorException {
	        
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        try {
        	String txtMinEntreCanciones = "01:00:00";
			try{
				txtMinEntreCanciones = ConfigurationParametersManager.getParameter(GlobalNames.PARAM_MIN_ENTRE_CANCIONES_LONG_FORMAT);
			}catch(MissingConfigurationParameterException e){
				if (log.isWarnEnabled()) log.warn("No se ha encontrado el parametro " + GlobalNames.PARAM_MIN_ENTRE_CANCIONES_LONG_FORMAT);
			}
        	
            /* Create "preparedStatement". */
            String queryString = "SELECT COUNT(*) " +
            	" FROM cancion" +
            	" WHERE fchprmpet < (SELECT fchprmpet FROM cancion WHERE id=?) " +
            	" AND (fchultrep is null OR (now()-fchultrep)>?)";
            preparedStatement = connection.prepareStatement(queryString);
            
            /* Fill "preparedStatement". */
            int i = 1;
            preparedStatement.setInt(i++, idCancion);
            preparedStatement.setString(i++, txtMinEntreCanciones);
            
            /* Execute query. */
            resultSet = preparedStatement.executeQuery();
            
            /* Get results. */
            int num = 0;
            if (resultSet.next()) {
            	num = resultSet.getInt(1);
            }

            /* Return . */
            return num;
            
        } catch (SQLException e) {
            throw new InternalErrorException(e);    
        } finally {
            GeneralOperations.closeResultSet(resultSet);
            GeneralOperations.closeStatement(preparedStatement);
        }    
        
    }
	
	/**Listado de peticiones agrupadas por cancion, 
	 * apareceran primero las canciones que tengan una peticion mas antigua.
	 * = Cola
	 * Solo usado para listado no para calculos
	 * */
	public ArrayList findPeticiones(Connection connection)
		throws InternalErrorException {
	        
	    PreparedStatement preparedStatement = null;
	    ResultSet resultSet = null;
	    ArrayList rdo = new ArrayList();
	    try {
	    	
	        /* Create "preparedStatement". */
	        String queryString = "SELECT c.id as idCancion, titulo, autor, duracion, caratula, dedicable, fchUltRep, fchPrmPet, path," +
	        	"p.id as idPeticion, fchPeticion, dedicatoria" +
	        	" FROM peticion p JOIN cancion c ON p.idcancion = c.id" +
	        	" WHERE p.fchreproduccion is null" +
	            " ORDER BY p.fchpeticion, c.id";
	        preparedStatement = connection.prepareStatement(queryString);
	        
	        /* Execute query. */
	        resultSet = preparedStatement.executeQuery();
	        
	        /* Get results. */
	        
	        int i;
	        int antIdCancion = 0;
	        ArrayList peticiones = new ArrayList();
	        while (resultSet.next()){
		        i = 1;
		        int idCancion = resultSet.getInt(i++);
		        String titulo = resultSet.getString(i++);
		        String autor = resultSet.getString(i++);
		        Time duracion = resultSet.getTime(i++);
		        String caratula = resultSet.getString(i++);
		        boolean dedicable = resultSet.getBoolean(i++);
		        Timestamp fchUltRep = resultSet.getTimestamp(i++);
		        Timestamp fchPrmPet = resultSet.getTimestamp(i++);
		        String path = resultSet.getString(i++);
		        
		        int idPeticion = resultSet.getInt(i++);
		        Timestamp fchPeticion = resultSet.getTimestamp(i++);
		        String dedicatoria = resultSet.getString(i++);
		        
		        if (idCancion != antIdCancion){
		        	peticiones = new ArrayList();
			        rdo.add(new CancionCVO(idCancion, titulo, autor, duracion, caratula, dedicable, fchUltRep, fchPrmPet, path, peticiones));
		        }
		        peticiones.add(new PeticionVO(idPeticion, idCancion, fchPeticion, null, dedicatoria));
		        antIdCancion = idCancion;
	        }
	        /* Return  */
	        return rdo;
	        
	    } catch (SQLException e) {
	        throw new InternalErrorException(e);    
	    } finally {
	        GeneralOperations.closeResultSet(resultSet);
	        GeneralOperations.closeStatement(preparedStatement);
	    }    
	    
	}
	
	/**lista canciones reproducidas con sus peticiones
	 * Las canciones aleatorias no tienen peticiones
	 * Primera de la lista la mas antigua
	 * Ultima de la lista la que se esta reproduciendo
	 * Solo valida para la ultima MinutosEntreMismaCancion ya que sobreescribimos c.fchultrep y c.fchprmpet
	 * */
	public ArrayList cancionesReproducidas(Connection connection)
		throws InternalErrorException {
	        
	    PreparedStatement preparedStatement = null;
	    ResultSet resultSet = null;
	    ArrayList rdo = new ArrayList();
	    try {
	    	
	        /* Create "preparedStatement". */
	        String queryString = "SELECT c.id as idCancion, titulo, autor, duracion, caratula, dedicable, fchUltRep, fchPrmPet, path," +
	        	"p.id as idPeticion, fchPeticion, dedicatoria" +
	        	" FROM peticion p RIGHT JOIN cancion c ON p.idcancion = c.id and c.fchultrep=p.fchreproduccion" +
	        	" WHERE not c.fchultrep is null" +
	            " ORDER BY c.fchultrep desc";
	       
	        preparedStatement = connection.prepareStatement(queryString);
	        
	        /* Execute query. */
	        resultSet = preparedStatement.executeQuery();
	        
	        /* Get results. */
	        
	        int i;
	        int antIdCancion = 0;
	        ArrayList peticiones = new ArrayList();
	        while (resultSet.next()){
		        i = 1;
		        int idCancion = resultSet.getInt(i++);
		        String titulo = resultSet.getString(i++);
		        String autor = resultSet.getString(i++);
		        Time duracion = resultSet.getTime(i++);
		        String caratula = resultSet.getString(i++);
		        boolean dedicable = resultSet.getBoolean(i++);
		        Timestamp fchUltRep = resultSet.getTimestamp(i++);
		        Timestamp fchPrmPet = resultSet.getTimestamp(i++);
		        String path = resultSet.getString(i++);
		        
		        int idPeticion = resultSet.getInt(i++);
		        Timestamp fchPeticion = resultSet.getTimestamp(i++);
		        String dedicatoria = resultSet.getString(i++);
		        
		        if (idCancion != antIdCancion){
		        	peticiones = new ArrayList();
			        rdo.add(new CancionCVO(idCancion, titulo, autor, duracion, caratula, dedicable, fchUltRep, fchPrmPet, path, peticiones));
		        }
		        //las canciones elegidas aleatoriamente no tienen peticiones
		        log.debug("** idPeticion "+idPeticion);
		        if(idPeticion!=0){
		        	log.debug("anadida pet");
		        	peticiones.add(new PeticionVO(idPeticion, idCancion, fchPeticion, null, dedicatoria));
		        }
		        antIdCancion = idCancion;
	        }
	        /* Return  */
	        return rdo;
	        
	    } catch (SQLException e) {
	        throw new InternalErrorException(e);    
	    } finally {
	        GeneralOperations.closeResultSet(resultSet);
	        GeneralOperations.closeStatement(preparedStatement);
	    }    
	    
	}

}
